package com.cooldatasoft.support;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.security.access.AccessDeniedException;

import com.cooldatasoft.exception.TaskManagerException;
import com.cooldatasoft.exception.TaskManagerUserException;


public class ExceptionHandlingAspect {

  private static Logger logger = Logger.getLogger(ExceptionHandlingAspect.class);
  private int order;

  public Object handleException(ProceedingJoinPoint call) throws Throwable {
    Object point = null;

    try {
      point = call.proceed();

    } catch (TaskManagerUserException e) { // pouzivatelske len rethrownem
      throw e;
    } catch (TaskManagerException e) {
      if (!e.isLogged()) { // normalne zalogujem (ak uz neboli)
        e.setLogged(true);
        logger.error(e.getMessage(), e);
      }
      throw e;
    } catch (RuntimeException e) { // niektore Spring runtimove vynimky nie su
                                   // aplikacne chyby

      // ak by aplikacia podporovala pesimisticky lock, poriesit
      // PessimisticLockingFailureException
      if (e instanceof OptimisticLockingFailureException) {
        logger.warn(e.getMessage(), e);
        throw new TaskManagerUserException("exception.optimisticLock",
            "Operation tried to access stale data. Try to refresh this page.");
      }
      if (e instanceof ObjectRetrievalFailureException) {
        logger.warn(e.getMessage(), e);
        throw new TaskManagerUserException("exception.objectNotFound",
            "Requested data does not exist, maybe due to deletion by another person. Try to refresh this page.");
      }
      if (e instanceof AccessDeniedException) {
        logger.warn("Unathorized method call!", e);
        throw new TaskManagerUserException("exception.accessDenied", "You have no rights to use this fuctionality", e);
      }
      if (e instanceof DataIntegrityViolationException) {
        logger.warn(e.getMessage(), e);
        throw new TaskManagerUserException("exception.dataIntegrity", "Data integrity violation: " + e.getMessage());
      }
      TaskManagerException ie = new TaskManagerException(e.getMessage() != null ? e.getMessage() : "Runtime exception", e);
      ie.setLogged(true);
      logger.error(ie.getMessage(), e);
      throw ie;

    } catch (Exception e) { // tu by sme sa nemali dostat, ak su service metody
                            // spravne naprogramovane
      TaskManagerException ie = new TaskManagerException(e.getMessage(), e);
      ie.setLogged(true);
      logger.error(e.getMessage(), e);
      throw ie;
    }

    return point;
  }

  public int getOrder() {
    return this.order;
  }

  public void setOrder(int order) {
    this.order = order;
  }
}
